package com.yeyks.hotel.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yeyks.hotel.dal.domain.HotelInfo;
import com.yeyks.common.dto.CashOutHotelManagePageDTO;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.hotel.dal.dao.HotelCommissionBillMapper;
import com.yeyks.hotel.dal.dao.HotelCommissionMapper;
import com.yeyks.hotel.dal.domain.CashOutHotel;
import com.yeyks.hotel.dal.dao.CashOutHotelMapper;
import com.yeyks.hotel.dal.domain.HotelCommission;
import com.yeyks.hotel.dal.domain.HotelCommissionBill;
import com.yeyks.hotel.service.CashOutHotelService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeyks.common.ajax.AjaxResponseBody;
import com.yeyks.common.param.CashOutHotelSelectForHotelPageParam;
import com.yeyks.common.param.CashOutHotelSelectForManagePageParam;
import com.yeyks.common.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


/**
 * <p>
 * 酒店提现订单表 服务实现类
 * </p>
 *
 * @author yun
 * @since 2019-06-25
 */
@Service
public class CashOutHotelServiceImpl extends ServiceImpl<CashOutHotelMapper, CashOutHotel> implements CashOutHotelService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private HotelCommissionMapper hotelCommissionMapper;
    @Autowired
    private HotelCommissionBillMapper hotelCommissionBillMapper;

    private String redisLockCashWithdrawalOperation = "redislock:CashOutHotelServiceImpl:cashWithdrawalOperation";

    @Override
    public AjaxResponseBody selectForManagePage(CashOutHotelSelectForManagePageParam cashOutHotelSelectForManagePageParam) {
        PageHelper.startPage(cashOutHotelSelectForManagePageParam.getPageNum(), cashOutHotelSelectForManagePageParam.getPageSize());
        List<CashOutHotelManagePageDTO> cashOutHotelManagePageDTOS = baseMapper.selectForManagePage(cashOutHotelSelectForManagePageParam.getHotelName(), cashOutHotelSelectForManagePageParam.getStatus());
        for (CashOutHotelManagePageDTO cashOutHotelManagePageDTO : cashOutHotelManagePageDTOS) {
            try{
                String payAccounts = cashOutHotelManagePageDTO.getPayAccounts();
                JSONObject pay_accounts = JSON.parseObject(payAccounts).getJSONObject("pay_accounts");
                String bankCard = pay_accounts.getString("bankCard");
                String bankName = pay_accounts.getString("bankName");
                String userName = pay_accounts.getString("userName");
                cashOutHotelManagePageDTO.setBankCard(bankCard).setBankName(bankName).setUserName(userName);
            }catch (Exception e){
                cashOutHotelManagePageDTO.setBankCard("").setBankName("银行卡信息不存在").setUserName("");
            }
        }
        PageInfo<CashOutHotelManagePageDTO> pageInfo = new PageInfo<>(cashOutHotelManagePageDTOS);
        return AjaxResponseBody.success(pageInfo);
    }

    @Override
    public AjaxResponseBody selectForHotelPage(CashOutHotelSelectForHotelPageParam cashOutHotelSelectForHotelPageParam) {
        PageHelper.startPage(cashOutHotelSelectForHotelPageParam.getPageNum(), cashOutHotelSelectForHotelPageParam.getPageSize());
        List<CashOutHotel> cashOutHotelEntities = baseMapper.selectList(new QueryWrapper<CashOutHotel>().eq(CashOutHotel.HOTEL_ID, cashOutHotelSelectForHotelPageParam.getHotelId()).orderByDesc(CashOutHotel.GMT_CREATE));
        PageInfo<CashOutHotel> pageInfo = new PageInfo<>(cashOutHotelEntities);
        return AjaxResponseBody.success(pageInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResponseBody cashWithdrawalOperation(HotelInfo hotelInfo, Integer amount) {
        if (null == hotelInfo) {
            throw new ServiceException("参数错误");
        }
        if (null == amount || amount <= 0) {
            throw new ServiceException("参数错误");
        }
        //锁
        return redisUtil.runWithLock(redisLockCashWithdrawalOperation, 10, 10, () -> {
            //查询酒店佣金
            HotelCommission hotelCommission = hotelCommissionMapper.selectOne(new QueryWrapper<HotelCommission>().eq(HotelCommission.HOTEL_ID, hotelInfo.getId()).eq(HotelCommission.TYPE, 1));
            Integer remainAmount = hotelCommission.getRemainAmount();
            Integer waitAmount = hotelCommission.getWaitAmount();
            if (amount > (remainAmount - waitAmount)) {
                throw new ServiceException("提现金额超过可提取金额");
            }
            //修改佣金记录
            hotelCommission.setRemainAmount(remainAmount - amount);
            int update = hotelCommissionMapper.update(hotelCommission
                    , new UpdateWrapper<HotelCommission>()
                            .eq(HotelCommission.ID, hotelCommission.getId())
                            .eq(HotelCommission.REMAIN_AMOUNT, remainAmount));
            if (update < 1) {
                throw new ServiceException("提现出错,佣金数据已被修改");
            }
            String cashOrderNo = IdWorker.getIdStr();
            //添加佣金修改记录
            HotelCommissionBill hotelCommissionBill = new HotelCommissionBill();
            hotelCommissionBill.setHotelId(hotelInfo.getId());
            hotelCommissionBill.setOrderNo(cashOrderNo);
            hotelCommissionBill.setHotelCommissionId(hotelCommission.getId());
            hotelCommissionBill.setOperatorAmount(-amount);
            hotelCommissionBill.setRemainAmount(remainAmount - amount);
            hotelCommissionBill.setStatus(0);
            hotelCommissionBill.setType(1);
            int insert = hotelCommissionBillMapper.insert(hotelCommissionBill);
            if (insert < 1) {
                throw new ServiceException("提现出错,佣金修改记录添加失败");
            }
            //添加佣金审批记录
            CashOutHotel cashOutHotel = new CashOutHotel();
            cashOutHotel.setOrderNo(cashOrderNo);
            cashOutHotel.setHotelId(hotelInfo.getId());
            cashOutHotel.setStatus(1);
            cashOutHotel.setPhone(hotelInfo.getPhone());
            cashOutHotel.setRemark("");
            cashOutHotel.setAmount(amount);
            cashOutHotel.setDeleteFlag(0);
            boolean save = save(cashOutHotel);
            if (!save) {
                throw new ServiceException("提现出错,佣金审批记录添加失败");
            }
            return AjaxResponseBody.success(cashOutHotel);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResponseBody updateStatus(Integer id, Integer status, String remark) {
        if (null == id) {
            throw new ServiceException("参数错误");
        }
        if (null == status || status <= 0) {
            throw new ServiceException("参数错误");
        }
        //锁
        return redisUtil.runWithLock(redisLockCashWithdrawalOperation, 10, 10, () -> {
            CashOutHotel cashOutHotel = getById(id);
            Integer oldStatus = cashOutHotel.getStatus();
            if (1 == status || 2 == oldStatus || 3 == oldStatus || 4 == oldStatus) {
                throw new ServiceException("状态更新失败,只能从1=>2,3,4");
            }
            HotelCommissionBill hotelCommissionBill;
            int updateHotelCommissionBillEntity = 0;
            switch (status) {
                case 2:
                    //修改佣金修改记录状态
                    hotelCommissionBill = hotelCommissionBillMapper.selectOne(
                            new QueryWrapper<HotelCommissionBill>()
                                    .eq(HotelCommissionBill.HOTEL_ID, cashOutHotel.getHotelId())
                                    .eq(HotelCommissionBill.ORDER_NO, cashOutHotel.getOrderNo()));
                    hotelCommissionBill.setStatus(1);
                    updateHotelCommissionBillEntity = hotelCommissionBillMapper.updateById(hotelCommissionBill);
                    if (updateHotelCommissionBillEntity < 1) {
                        throw new ServiceException("状态更新失败(佣金修改记录)");
                    }
                    break;
                case 3:
                case 4:
                    //修改佣金修改记录状态
                    hotelCommissionBill = hotelCommissionBillMapper.selectOne(
                            new QueryWrapper<HotelCommissionBill>()
                                    .eq(HotelCommissionBill.HOTEL_ID, cashOutHotel.getHotelId())
                                    .eq(HotelCommissionBill.ORDER_NO, cashOutHotel.getOrderNo()));
                    hotelCommissionBill.setStatus(2);
                    updateHotelCommissionBillEntity = hotelCommissionBillMapper.updateById(hotelCommissionBill);
                    if (updateHotelCommissionBillEntity < 1) {
                        throw new ServiceException("状态更新失败(佣金修改记录)");
                    }
                    //返还佣金
                    HotelCommission hotelCommission = hotelCommissionMapper.selectOne(new QueryWrapper<HotelCommission>()
                            .eq(HotelCommission.HOTEL_ID, cashOutHotel.getHotelId())
                            .eq(HotelCommission.TYPE, 1));
                    Integer remainAmount = hotelCommission.getRemainAmount();
                    hotelCommission.setRemainAmount(remainAmount + Math.abs(hotelCommissionBill.getOperatorAmount()));
                    int updateHotelCommissionEntity = hotelCommissionMapper.update(hotelCommission
                            , new UpdateWrapper<HotelCommission>()
                                    .eq(HotelCommission.ID, hotelCommission.getId())
                                    .eq(HotelCommission.REMAIN_AMOUNT, remainAmount));
                    if (updateHotelCommissionEntity < 1) {
                        throw new ServiceException("状态更新失败(返还佣金失败)");
                    }
                    break;
            }
            cashOutHotel.setStatus(status);
            cashOutHotel.setRemark(remark);
            boolean b = updateById(cashOutHotel);
            if (!b) {
                throw new ServiceException("状态更新失败()");
            }
            return AjaxResponseBody.success();
        });
    }
}
